package es.unex.meigas.core;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import java.awt.geom.Ellipse2D;
import java.util.ArrayList;

import es.unex.meigas.gui.SimpleViewPanel;
import es.unex.meigas.gui.World2Device;

public class ConcentricPlot extends Plot {

	private static final int PLOTS_COUNT = 5;
	private Double[] m_dRadius;
	private Double[] m_dMinDiameter;

	public ConcentricPlot(){

		super();

		int i;

		m_dRadius = new Double[PLOTS_COUNT];
		m_dMinDiameter = new Double[PLOTS_COUNT];

		for (i = 0; i < PLOTS_COUNT; i++){
			m_dRadius[i] = new Double(NO_DATA);
			m_dMinDiameter[i] = new Double(NO_DATA);
		}

	}

	public Double[] getRadius() {

		return m_dRadius;

	}

	public void setRadius(Double[] dRadius) {

		int i;

		for (i = 0; i < dRadius.length; i++){
			if (!dRadius[i].equals(m_dRadius[i])){
				m_dRadius[i] = dRadius[i];
				setHasChanged(true);
			}
		}

	}

	public Double[] getMinAcceptableDiameters() {

		return m_dMinDiameter;

	}

	public void setMinAcceptableDiameters(Double[] dDiameter) {

		int i;

		for (i = 0; i < dDiameter.length; i++){
			if (!dDiameter[i].equals(m_dMinDiameter[i])){
				m_dMinDiameter[i] = dDiameter[i];
				setHasChanged(true);
			}
		}

	}

	public double getArea(){

		double dRadius = getMaxRadius();

		if (dRadius != NO_DATA){
			return (Math.PI * Math.pow(dRadius, 2.) / 10000.);
		}
		else{
			return NO_DATA;
		}

	}


	public double getMaxRadius(){

		int i;
		int iIndex = -1;

		for (i = 0; i < PLOTS_COUNT; i++){
			if (m_dRadius[i].doubleValue() == NO_DATA){
				iIndex = i - 1;
				break;
			}
		}

		if (iIndex >= 0){
			return m_dRadius[iIndex].doubleValue();
		}
		else{
			return NO_DATA;
		}

	}

	public Rectangle2D getBoundingBox() {

		double dRadius = getMaxRadius();

		if (dRadius != NO_DATA){
			return new Rectangle2D.Double(m_CoordX - dRadius,
										  m_CoordY - dRadius,
										  dRadius * 2,
										  dRadius * 2);
		}
		else{
			return null;
		}

	}

	public void paint(Graphics g, World2Device w2d) {

		int i;

		for (i = 0; i < PLOTS_COUNT; i++){
			if (m_dRadius[i].doubleValue() != NO_DATA){
				Graphics2D g2 = (Graphics2D) g;
				Point2D pt = new Point2D.Double(m_CoordX - m_dRadius[i].doubleValue(),
												m_CoordY + m_dRadius[i].doubleValue());
				pt = w2d.transformPoint(pt);
				double dRadius = w2d.transformDistance(m_dRadius[i].doubleValue());
				Ellipse2D ellipse = new Ellipse2D.Double(pt.getX() + SimpleViewPanel.MARGIN,
														pt.getY() + SimpleViewPanel.MARGIN,
						 								2 * dRadius, 2 * dRadius);

				g2.setColor(m_Color);
				//g2.fill(ellipse);
				g2.setColor(Color.BLACK);
				g2.draw(ellipse);
			}
			else{
				break;
			}
		}

	}

	public double[] getDistribution(String sSpecie, int iInterval, int iParameter){

		int i, j;
		int iCount;
		int iClass, iClass2;
		int iClasses;
		int iMaxDiameter;
		int iTreesCount = 0;
		double dDiameter;
		double dValue;
		double area[];
		String s;
		ArrayList trees = getTrees(getFilters());
		Tree tree;

		iMaxDiameter = (int) Math.ceil(getMaximumDiameter(trees));
		iClasses = iMaxDiameter;

		if (iClasses == 0){
			return null;
		}

		area = new double[iClasses];

		iCount = getConcentricPlotsCount();
		if (iCount == 0){
			return null;
		}

		for (i = 0; i < iClasses; i++){
			for (j = 0 ; j < iCount; j++){
				if (i < m_dMinDiameter[j].doubleValue()){
					break;
				}
			}
			if (j == 0){
				area[i] = (Math.PI * Math.pow(m_dRadius[0].doubleValue(), 2.) / 10000.);
			}
			else{
				area[i] = (Math.PI * Math.pow(m_dRadius[j - 1].doubleValue(), 2.) / 10000.);
			}
		}

		double distribution[] = new double[iClasses];
		int treesCount[] = new int [iClasses];

		for (i = 0; i < iClasses; i++){
			distribution[i] = 0;
			treesCount[i] = 0;
		}

		for (i = 0; i < trees.size(); i++){
			tree = (Tree)trees.get(i);
			s = tree.getSpecie();
			if (s.equals(sSpecie) || sSpecie.equals("Todas")){
				dDiameter = tree.getDBH().getValue();
				if (dDiameter!= NO_DATA){
					switch (iParameter){
					case FREQUENCY:
						dValue = 1;
						break;
					case HEIGHT:
						dValue = tree.getHeight().getValue();
						break;
					case LOG_HEIGHT:
						dValue = tree.getLogHeight().getValue();
						break;
					case VOLUME:
						dValue = tree.getVolumeWithBark().getValue();
						break;
					case VOLUME_WITHOUT_BARK:
						dValue = tree.getVolumeWithoutBark().getValue();
						break;
					case AGE:
						dValue = tree.getAge().getValue();
						break;
					case BASIMETRIC_AREA:
						dValue = tree.getBasimetricArea();
						break;
					default:
						return null;
					}
					if (dValue!= NO_DATA){
						iClass = (int) Math.floor(dDiameter);
						iClass = Math.min(iClass, iClasses - 1);
						distribution[iClass] += dValue;
						treesCount[iClass]++;
					}
				}
			}
		}

		if (iParameter == FREQUENCY){
			for (i = 0; i < iClasses; i++){
				distribution[i] /= area[i];
			}
		}

		iClasses = (int) Math.ceil((double)iMaxDiameter / (double) iInterval);
		double ret[] = new double[iClasses];

		for (i = 0; i < iClasses; i++){
			ret[i] = 0;
		}

		for (iClass = 0, iClass2 = 0; iClass < iClasses; iClass++, iClass2+=iInterval){
			iTreesCount = 0;
			for (i = 0; i < iInterval;i++){
				if (iClass2 + i < iMaxDiameter){
					ret[iClass] += distribution[iClass2 + i];
					iTreesCount += treesCount[iClass2 + i];
				}
			}
			if (iParameter != FREQUENCY){
				if (iTreesCount != 0){
					ret[iClass] /= ((double)iTreesCount);
				}
			}
		}

		return ret;

	}

	private int getConcentricPlotsCount(){

		int i;

		for (i = 0; i < PLOTS_COUNT; i++){
			if (m_dRadius[i].doubleValue() == NO_DATA && m_dMinDiameter[i].doubleValue() == NO_DATA){
				break;
			}
		}

		return i;
	}

	protected boolean checkData() {

		return super.checkData();

	}

	public DasocraticElement getNewInstance(){

		ConcentricPlot plot = (ConcentricPlot) super.getNewInstance();
		plot.setRadius(getRadius());
		plot.setMinAcceptableDiameters(getMinAcceptableDiameters());

		return plot;


	}


}